﻿using System.Windows;
using System.Windows.Input;

using ICSharpCode.AvalonEdit;
using ICSharpCode.AvalonEdit.Editing;
using ICSharpCode.AvalonEdit.Folding;
using ICSharpCode.AvalonEdit.Highlighting;

namespace Jerry.DroidBuilder.Extensions
{
    public static class TextEditorExtension
    {
        #region BindableText

        public static string GetBindableText(DependencyObject obj)
        {
            return (string)obj.GetValue(BindableTextProperty);
        }

        public static void SetBindableText(DependencyObject obj, string value)
        {
            obj.SetValue(BindableTextProperty, value);
        }

        public static readonly DependencyProperty BindableTextProperty =
            DependencyProperty.RegisterAttached("BindableText", typeof(string), typeof(TextEditorExtension), new PropertyMetadata(null, OnBindableTextChanged));

        private static void OnBindableTextChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            var editor = sender as TextEditor;
            var text = GetBindableText(sender);

            if (null == editor || null == text)
            {
                return;
            }

            editor.Text = text;
        }

        #endregion

        #region TextFormat

        public static string GetTextFormat(DependencyObject obj)
        {
            return (string)obj.GetValue(TextFormatProperty);
        }

        public static void SetTextFormat(DependencyObject obj, string value)
        {
            obj.SetValue(TextFormatProperty, value);
        }

        public static readonly DependencyProperty TextFormatProperty =
            DependencyProperty.RegisterAttached("TextFormat", typeof(string), typeof(TextEditorExtension), new PropertyMetadata(null, OnTextFormatChanged));

        private static void OnTextFormatChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            var editor = sender as TextEditor;
            var format = GetTextFormat(sender);

            if (null == editor || null == format)
            {
                return;
            }

            var textArea = editor.TextArea;

            textArea.TextEntered += OnTextAreaTextEntered;

            switch (format.ToLowerInvariant())
            {
                case ".xml":
                    if (null == editor.SyntaxHighlighting)
                    {
                        editor.SyntaxHighlighting = HighlightingManager.Instance.GetDefinition("XML");

                        var foldingManager = FoldingManager.Install(textArea);
                        var foldingStrategy = new XmlFoldingStrategy();

                        SetFoldingManager(textArea, foldingManager);
                        SetFoldingStrategy(textArea, foldingStrategy);

                        foldingStrategy.UpdateFoldings(foldingManager, editor.Document);
                    }
                    break;
                default:
                    break;
            }
        }

        #endregion

        #region FoldingStrategy

        public static AbstractFoldingStrategy GetFoldingStrategy(DependencyObject obj)
        {
            return (AbstractFoldingStrategy)obj.GetValue(FoldingStrategyProperty);
        }

        private static void SetFoldingStrategy(DependencyObject obj, AbstractFoldingStrategy value)
        {
            obj.SetValue(FoldingStrategyPropertyKey, value);
        }

        private static readonly DependencyPropertyKey FoldingStrategyPropertyKey =
            DependencyProperty.RegisterAttachedReadOnly("FoldingStrategy", typeof(AbstractFoldingStrategy), typeof(TextEditorExtension), new PropertyMetadata(null));

        private static readonly DependencyProperty FoldingStrategyProperty = FoldingStrategyPropertyKey.DependencyProperty;

        #endregion

        #region FoldingManager

        public static FoldingManager GetFoldingManager(DependencyObject obj)
        {
            return (FoldingManager)obj.GetValue(FoldingManagerProperty);
        }

        private static void SetFoldingManager(DependencyObject obj, FoldingManager value)
        {
            obj.SetValue(FoldingManagerPropertyKey, value);
        }

        private static readonly DependencyPropertyKey FoldingManagerPropertyKey =
            DependencyProperty.RegisterAttachedReadOnly("FoldingManager", typeof(FoldingManager), typeof(TextEditorExtension), new PropertyMetadata(null));

        private static readonly DependencyProperty FoldingManagerProperty = FoldingManagerPropertyKey.DependencyProperty;

        #endregion

        private static void OnTextAreaTextEntered(object sender, TextCompositionEventArgs e)
        {
            var textArea = sender as TextArea;
            var strategy = GetFoldingStrategy(textArea as DependencyObject);
            var manager = GetFoldingManager(textArea as DependencyObject);

            strategy.UpdateFoldings(manager, textArea.Document);
        }
    }
}
